package main

import (
	"encoding/hex"
	"fmt"
	"github.com/dromara/dongle"
	"github.com/duke-git/lancet/v2/fileutil"
	"github.com/thoas/go-funk"
	"gorm.io/driver/postgres"
	"gorm.io/gorm"
	"log"
	"strings"
	"time"
	platformQuery "xiuxianActive/dao/xialou_platform/gen"
	"xiuxianActive/model/res"
	"xiuxianActive/utils"
)

var (
	dbTest1 *gorm.DB
	dbTest2 *gorm.DB
	db1     *gorm.DB // 生产环境 - 休闲吧
	db2     *gorm.DB // 生产环境 - 销氪
)

func InitDB() {
	var err error
	// 测试环境
	//dbPath1 := "postgres://postgres:eF1d789f2ba7d..@127.0.0.1:5434/xiuxian_db?sslmode=disable"
	//dbPath2 := "postgres://postgres:eF1d789f2ba7d..@127.0.0.1:5434/xialou_platform?sslmode=disable"
	// 生产环境
	dbPath1 := "postgres://xlkj:QgnpJk8eopt7Fv2..@127.0.0.1:5435/xiuxian_db?sslmode=disable"
	dbPath2 := "postgres://xlkj:QgnpJk8eopt7Fv2..@127.0.0.1:5436/xialou_platform?sslmode=disable"
	db1, err = gorm.Open(postgres.Open(dbPath1), &gorm.Config{
		PrepareStmt: true,
	})
	db2, err = gorm.Open(postgres.Open(dbPath2), &gorm.Config{
		PrepareStmt: true,
	})
	if err != nil {
		panic("failed to connect database")
	}
}

func ReadCardFile(path string) []res.BoxInfo {
	// "./files/30000.xlsx"
	_, boxesInfo := utils.LoadCardDoc(path)
	return boxesInfo
}

func BindCardByBoxIndex(boxesInfo []res.BoxInfo, startBox, endBox int64, proxy string, enable bool, update bool) {

	//db1Query := xiuxianQuery.Use(db1)
	db2Query := platformQuery.Use(db2)

	agentQuery := db2Query.Agent
	agent, err := agentQuery.Where(agentQuery.Phone.Like("%" + proxy + "%")).First()
	if err != nil {
		log.Fatal("获取代理失败", err)
		panic(err)
	}
	fmt.Println(fmt.Sprintf("代理: %s", agent.RealName))

	//cardQuery := db1Query.UsersInviteCard
	total := int64(0)
	for i := startBox; i <= endBox; i++ {
		box := boxesInfo[i-1]
		fmt.Println(fmt.Sprintf("盒子 %d", i))
		for j := 0; j < len(box.List); j++ {
			stage := box.List[j]
			fmt.Println(fmt.Sprintf("阶段 %d: %d - %d", j+1, stage.StartNum, stage.EndNum))
			count := OperateCardByRange(stage.StartNum, stage.EndNum, agent.ID, enable, update)
			total += count
			fmt.Println(fmt.Sprintf("总数: %d", count))
		}
	}
	fmt.Println(fmt.Sprintf("代理ID: %d", agent.ID))
	fmt.Println(fmt.Sprintf("代理: %s", agent.RealName))
	fmt.Println(fmt.Sprintf("总数: %d", total))
}

// OpenCardByStage 阶段开启

func OpenCardByStage(startNum, endNum int64, enable bool, proxy string, update bool) int64 {
	db2Query := platformQuery.Use(db2)
	agentQuery := db2Query.Agent
	agent, err := agentQuery.Where(agentQuery.Phone.Like("%" + proxy + "%")).First()
	if err != nil {
		log.Fatal("获取代理失败", err)
		panic(err)
	}
	count := OperateCardByRange(startNum, endNum, agent.ID, enable, update)
	fmt.Println(fmt.Sprintf("代理ID: %d", agent.ID))
	fmt.Println(fmt.Sprintf("代理: %s", agent.RealName))
	fmt.Println(fmt.Sprintf("总数: %d", count))
	return count
}

// OperateCardByRange 范围操作卡片
func OperateCardByRange(startNum, endNum int64, parentId int64, enable bool, update bool) int64 {
	count := 0
	err := db1.Raw("SELECT count(1) FROM users_invite_card WHERE access_key ~ '^[0-9]+$' AND access_key::INTEGER BETWEEN ? AND ?", startNum, endNum).Scan(&count).Error
	if err != nil {
		panic(err)
	}

	// 随机字符串
	card, _ := utils.GenerateRandomString(10)
	// 当前时间
	timeNow := time.Now()

	if update {
		// 更新这些卡片的代理
		err = db1.Exec("UPDATE users_invite_card SET parent_uid = ?, enabled = ?, sub_batch_code = ?, sub_batch_create_time = ? WHERE access_key ~ '^[0-9]+$' AND access_key::INTEGER BETWEEN ? AND ?", parentId, enable, card, timeNow, startNum, endNum).Error
		if err != nil {
			panic(err)
		}
	}
	return int64(count)
}

func Fix(startNum, endNum int64) {
	type Card struct {
		Id        int64
		ParentUid int64
		Enabled   bool
	}
	var cards []Card
	err := db1.Raw("SELECT * FROM users_invite_card WHERE access_key ~ '^[0-9]+$' AND access_key::INTEGER BETWEEN ? AND ? order by id asc", startNum, endNum).Scan(&cards).Error
	if err != nil {
		panic(err)
	}
	for i, card := range cards {
		// 更新这些卡片的代理
		err := db1.Exec("UPDATE users_invite_card SET parent_uid = ?, enabled = ? WHERE id = ?", card.ParentUid, card.Enabled, card.Id).Error
		if err != nil {
			panic(err)
		}
		fmt.Println(i+1, card.Id, card.ParentUid, card.Enabled, "更新成功")
	}
	//fmt.Println(len(cards))
}

//INSERT INTO "users_invite_card"("status","card_code","year","parent_uid","uid","message","create_time","update_time","uq_key","batch_id","access_key","access_secret","enabled","usage_count","paid","special_usage_count","price","cover","general_count_remain","special_count_remain","activation_deadline","valid_days","card_type") VALUES(null,'b63618816427b4037fe7d197f7980cfd',1,1838092619146641408,0,'','2024-08-14 11:18:50.625805+08','2024-08-14 11:18:50.625805+08',205220,1823559881978834944,'77002654','tjYYgWQntAN/59GX95gM/Q==','true',null,'true',30,49800,'https://hesen-gfn-public.oss-cn-shenzhen.aliyuncs.com/2024/08/14/YmU4ZTRmZWY3YWFlNGRlZDI4NDNmNzUwYzE1ZWZhZjU%3D.jpg',null,30,'2025-03-01 00:00:00+08',365,1);

// active 是否激活 status 是否被使用
func GetCatAccessKeyAnyAccessSecretByName(name string, active, status bool) ([]res.KeyAndSecret, error) {
	var (
		err error
	)
	type idModel struct {
		ID int64
	}
	var idM idModel
	if err = db2.Table("agent").Select("id").Where("real_name = ?", name).First(&idM).Error; err != nil {
		return nil, err
	}
	var keyAndSecrets []res.SearchModel
	searchSQL := db1.Debug().Table("users_invite_card").Select("access_key", "access_secret", "status", "enabled").Where("parent_uid = ?", idM.ID)
	if active {
		searchSQL = searchSQL.Where("enabled = true")
	}
	if status {
		searchSQL = searchSQL.Where("status = true")
	}
	if err = searchSQL.Find(&keyAndSecrets).Error; err != nil {
		return nil, err
	}
	cipher := GetAesCipher()
	var (
		resKey []res.KeyAndSecret
		data   [][]string
	)
	data = [][]string{{"access_key", "access_secret", "是否激活", "是否被使用"}}
	for _, v := range keyAndSecrets {
		var temp res.KeyAndSecret
		secret := dongle.Decrypt.FromBase64String(v.AccessSecret).ByAes(cipher).ToString()
		deArr := strings.Split(secret, "-")
		if len(deArr) > 1 {
			temp.AccessKey = deArr[0]
			temp.AccessSecret = deArr[1]
		}
		data = append(data, []string{temp.AccessKey, temp.AccessSecret, fmt.Sprintf("%s", funk.ShortIf(v.Enabled, "是", "否")), fmt.Sprintf("%s", funk.ShortIf(v.Status, "是", "否"))})
		resKey = append(resKey, temp)
	}
	fileutil.WriteCsvFile("./files/"+name+".csv", data, false)
	return resKey, err
}

var key = "5406f826522a4320bedabeb6278fd1e0"
var iv = "7a84b8e1e9d34f7c349341c451cc864c"

func GetAesCipher() *dongle.Cipher {
	k, _ := hex.DecodeString(key)
	i, _ := hex.DecodeString(iv)
	cipher := dongle.NewCipher()
	cipher.SetMode(dongle.CTR) // CBC、CFB、OFB、CTR、ECB
	cipher.SetPadding(dongle.PKCS7)
	cipher.SetKey(string(k)) // key 长度必须是 16、24 或 32 字节
	cipher.SetIV(string(i))  // iv must be 16 bytes (ECB mode doesn't require setting iv)
	return cipher
}
